<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  
  <title>微信小程序结合ThinkPHP5实战项目（三）-- 微信登录与令牌 | 程序小工  | Just do it!</title>
  <meta name="description" content="遇见更好的自己~" />
  <meta name="keywords" content="" />
  <meta name="HandheldFriendly" content="True" />
  <meta name="apple-mobile-web-app-capable" content="yes">
  <link rel="shortcut icon" href="/">
  <link rel="alternate" href="/atom.xml" title="程序小工  | Just do it!">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <meta name="description" content="ThinkPHP5 从入门到深入学习，结合实战项目深入理解 ThinkPHP5 的特性和使用方法。深入学习 api 开发，学习微信登录和令牌的相关知识，并理解微信登录流程，完成与微信开放 api 之间的数据交互，完善项目的相应功能。 理解第三方登录授权的 code 和 token 交互过程。">
<meta name="keywords" content="thinkphp5,微信小程序">
<meta property="og:type" content="article">
<meta property="og:title" content="微信小程序结合ThinkPHP5实战项目（三）-- 微信登录与令牌">
<meta property="og:url" content="http://blog.i2arch.tech/2018/07/11/php-practice-wx-tp5-3/index.html">
<meta property="og:site_name" content="程序小工  | Just do it!">
<meta property="og:description" content="ThinkPHP5 从入门到深入学习，结合实战项目深入理解 ThinkPHP5 的特性和使用方法。深入学习 api 开发，学习微信登录和令牌的相关知识，并理解微信登录流程，完成与微信开放 api 之间的数据交互，完善项目的相应功能。 理解第三方登录授权的 code 和 token 交互过程。">
<meta property="og:locale" content="zh-Hans">
<meta property="og:image" content="https://raw.githubusercontent.com/zqunor/MarkdownPic/master/thinkphp5+%E5%B0%8F%E7%A8%8B%E5%BA%8F%E5%95%86%E5%9F%8E/9-2%E5%BE%AE%E4%BF%A1%E7%99%BB%E5%BD%95%E6%B5%81%E7%A8%8B.png">
<meta property="og:image" content="https://raw.githubusercontent.com/zqunor/MarkdownPic/master/thinkphp5+%E5%B0%8F%E7%A8%8B%E5%BA%8F%E5%95%86%E5%9F%8E/9-2%E4%BD%BF%E7%94%A8Token%E8%AE%BF%E9%97%AE%E4%B8%8B%E5%8D%95%E6%8E%A5%E5%8F%A3.png">
<meta property="og:updated_time" content="2018-08-15T10:23:56.934Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="微信小程序结合ThinkPHP5实战项目（三）-- 微信登录与令牌">
<meta name="twitter:description" content="ThinkPHP5 从入门到深入学习，结合实战项目深入理解 ThinkPHP5 的特性和使用方法。深入学习 api 开发，学习微信登录和令牌的相关知识，并理解微信登录流程，完成与微信开放 api 之间的数据交互，完善项目的相应功能。 理解第三方登录授权的 code 和 token 交互过程。">
<meta name="twitter:image" content="https://raw.githubusercontent.com/zqunor/MarkdownPic/master/thinkphp5+%E5%B0%8F%E7%A8%8B%E5%BA%8F%E5%95%86%E5%9F%8E/9-2%E5%BE%AE%E4%BF%A1%E7%99%BB%E5%BD%95%E6%B5%81%E7%A8%8B.png">
    
  <link href="https://fonts.googleapis.com/css?family=Inconsolata|Titillium+Web" rel="stylesheet">
  <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
  <link href='//cdn.bootcss.com/node-waves/0.7.5/waves.min.css' rel='stylesheet'>
  <link rel="stylesheet" href="/style.css">
  <script>
    function setLoadingBarProgress(num) {
      document.getElementById('loading-bar').style.width=num+"%";
    }
  </script>
</head>

<body>
  <div id="loading-bar-wrapper">
  <div id="loading-bar"></div>
</div>


  <script>setLoadingBarProgress(20)</script>
  <header class="l_header">
	<div class='wrapper'>
		<div class="nav-main container container--flex">
			<a class="logo flat-box" href='/' >
				程序小工  | Just do it!
			</a>
			<div class='menu'>
				<ul class='h-list'>
					
						<li>
							<a class='flat-box nav-home' href='/'>
								<i class='icon icon-list2'></i>
								首页
							</a>
						</li>
					
						<li>
							<a class='flat-box nav-archives' href='/archives'>
								<i class='icon icon-bookmark'></i>
								归档
							</a>
						</li>
					
						<li>
							<a class='flat-box nav-about' href='/about'>
								<i class='icon icon-user'></i>
								关于
							</a>
						</li>
					
				</ul>
				<div class='underline'></div>
			</div>
			
				<div class="m_search">
					<form name="searchform" class="form u-search-form">
						<input type="text" class="input u-search-input" placeholder="Search" />
						<span class="icon icon-search"></span>
					</form>
				</div>
			
			<ul class='switcher h-list'>
				
					<li class='s-search'><a href='javascript:void(0)'><span class="icon icon-search flat-box"></span></a></li>
				
				<li class='s-menu'><a href='javascript:void(0)'><span class="icon icon-menu flat-box"></span></a></li>
			</ul>
		</div>

		<div class='nav-sub container container--flex'>
			<a class="logo" class="flat-box" href='javascript:void(0)'>
				Word of Forks
			</a>

			<ul class='switcher h-list'>
				<li class='s-comment'><a href='javascript:void(0)'><span class="icon icon-chat_bubble_outline flat-box"></span></a></li>
				<li class='s-top'><a href='javascript:void(0)'><span class="icon icon-arrow_upward flat-box"></span></a></li>
				<li class='s-toc'><a href='javascript:void(0)'><span class="icon icon-format_list_numbered flat-box"></span></a></li>
			</ul>
		</div>
	</div>
</header>
<aside class="menu-phone">
	<nav>
		
			<a href="/" class="nav-home nav">
				首页
			</a>
		
			<a href="/archives" class="nav-archives nav">
				归档
			</a>
		
			<a href="/about" class="nav-about nav">
				关于
			</a>
		
	</nav>
</aside>

    <script>setLoadingBarProgress(40);</script>
  <div class="l_body">
    <div class='container clearfix'>
      <!-- 左侧内容 -->
      <div class='l_main'>
        <article id="post-php-practice-wx-tp5-3"
  class="post white-box article-type-post"
  itemscope itemprop="blogPost">
	<section class='meta'>

	<h2 class="title">
  	<a href="/2018/07/11/php-practice-wx-tp5-3/">
    	微信小程序结合ThinkPHP5实战项目（三）-- 微信登录与令牌
    </a>
	</h2>

	<div class="pagenav">
		<time>
			2018-07-11
		</time>

		
    
    <div class='cats'>
        <i class="icon icon-bookmark"></i>
        <a href="/categories/PHP/">PHP</a>
    </div>


		
			<div class="pagetags">
				<i class="icon icon-price-tag" style="margin-right: 2px;"></i>
				
					<a href="/tags/thinkphp5/" style="margin-left: 3px;">
						thinkphp5
					</a>
				
					<a href="/tags/微信小程序/" style="margin-left: 3px;">
						微信小程序
					</a>
				
			</div>
			
	</div>
	</section>

	
	<section class="toc-wrapper"><ol class="toc"><li class="toc-item toc-level-3"><a class="toc-link" href="#9-1-初识-token-意义与作用"><span class="toc-text"> 9-1 初识 Token - 意义与作用</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#9-2-微信登录流程"><span class="toc-text"> 9-2 微信登录流程</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#9-3-实现-token-身份权限体系"><span class="toc-text"> 9-3 实现 Token 身份权限体系</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#9-4567-实现-token-身份权限体系"><span class="toc-text"> 9-4/5/6/7 实现 Token 身份权限体系</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#9-8-获取请求参数-code-并调用-php-接口借助微信开发工具"><span class="toc-text"> 9-8 获取请求参数 code 并调用 PHP 接口[借助微信开发工具]</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#1微信开发者工具中配置"><span class="toc-text"> 1.微信开发者工具中配置：</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2小程序代码"><span class="toc-text"> 2.小程序代码：</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3请求-php-接口获取-token"><span class="toc-text"> 3.请求 PHP 接口获取 Token</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#9-9-商品详情接口"><span class="toc-text"> 9-9 商品详情接口</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#9-10-1-路由变量规则"><span class="toc-text"> 9-10-1 路由变量规则</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#9-10-2-路由分组"><span class="toc-text"> 9-10-2 路由分组</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#9-11-闭包函数构建查询器"><span class="toc-text"> 9-11 闭包函数构建查询器</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#9-12-用户收货地址"><span class="toc-text"> 9-12 用户收货地址</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#9-12-1-通过令牌获取用户标识"><span class="toc-text"> 9-12-1 通过令牌获取用户标识</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#9-12-2-面向对象的方式封装获取-uid-方法"><span class="toc-text"> 9-12-2 面向对象的方式封装获取 uid 方法</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#9-12-3-模型新增和更新"><span class="toc-text"> 9-12-3 模型新增和更新</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#9-12-4-参数过滤"><span class="toc-text"> 9-12-4 参数过滤</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#9-12-5-接口测试"><span class="toc-text"> 9-12-5 接口测试</span></a></li></ol></section>
	

	<section class="article typo">
		<div class="article-entry" itemprop="articleBody">
				<span class="zhaiyao">[摘要]</span>
			<p>ThinkPHP5 从入门到深入学习，结合实战项目深入理解 ThinkPHP5 的特性和使用方法。深入学习 api 开发，学习微信登录和令牌的相关知识，并理解微信登录流程，完成与微信开放 api 之间的数据交互，完善项目的相应功能。<br>
理解第三方登录授权的 code 和 token 交互过程。</p>
<a id="more"></a>
<h3 id="9-1-初识-token-意义与作用"><a class="markdownIt-Anchor" href="#9-1-初识-token-意义与作用"></a> 9-1 初识 Token - 意义与作用</h3>
<p>说明：目前这种情况下，用户只要知道了系统的接口的形式，就可以直接访问，并获取数据，而大多数情况下，我们需要对用户身份进行验证，如：需要用户登录后才能访问的接口，以及需要管理员才能访问的接口等。</p>
<p>1.获取令牌</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">客户端=》(账号、密码)=》getToken 《==》 账号、密码、Token、Auth</span><br></pre></td></tr></table></figure>
<p>描述：客户端携带账号和密码信息，调用<code>getToken</code>接口，经过处理验证后，返回账号、密码、Token、Auth 等信息。</p>
<p>2.访问接口</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">客户端=》(Token)=》下单接口 《==》 账号、密码、Token、Auth</span><br></pre></td></tr></table></figure>
<p>验证：1.是否合法 2.是否有效 3.是否有操作权限</p>
<p>3.上面两个过程的 getToken 接口和下单接口就是被保护的接口，需要验证通过才能让用户访问。</p>
<h3 id="9-2-微信登录流程"><a class="markdownIt-Anchor" href="#9-2-微信登录流程"></a> 9-2 微信登录流程</h3>
<p>1.微信身份登录体系</p>
<p><img src="https:raw.githubusercontent.com/zqunor/MarkdownPic/master/thinkphp5+%E5%B0%8F%E7%A8%8B%E5%BA%8F%E5%95%86%E5%9F%8E/9-2%E5%BE%AE%E4%BF%A1%E7%99%BB%E5%BD%95%E6%B5%81%E7%A8%8B.png" alt="微信登录流程"></p>
<p>2.Token 在接口验证时的使用流程</p>
<p><img src="https:raw.githubusercontent.com/zqunor/MarkdownPic/master/thinkphp5+%E5%B0%8F%E7%A8%8B%E5%BA%8F%E5%95%86%E5%9F%8E/9-2%E4%BD%BF%E7%94%A8Token%E8%AE%BF%E9%97%AE%E4%B8%8B%E5%8D%95%E6%8E%A5%E5%8F%A3.png" alt="Token访问下单接口"></p>
<h3 id="9-3-实现-token-身份权限体系"><a class="markdownIt-Anchor" href="#9-3-实现-token-身份权限体系"></a> 9-3 实现 Token 身份权限体系</h3>
<p>1.获取 token 的请求使用 post 方法[安全性方面考虑]</p>
<p>2.将复杂的业务分层到<code>service</code>层[实现分层思想]</p>
<p>使用模型处理数据库 CRUD 相关的操作，对于不操作数据库的复杂业务，将其封装到 Service 目录下，实现分层处理的思想，Service 层是在 Model 层之上的业务层。</p>
<p>3.基础实现</p>
<p>1）控制器的定义</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// api/controller/v1/Token [注意命名空间]</span></span><br><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">getToken</span><span class="params">($code = <span class="string">''</span>)</span> </span>&#123;&#125;</span><br></pre></td></tr></table></figure>
<p>2）路由定义</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// route.php</span></span><br><span class="line">Route::post(<span class="string">'api/:version/token/user'</span>, <span class="string">'api/:version.Token/getToken'</span>);</span><br></pre></td></tr></table></figure>
<p>3）验证器校验</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// api/controller/v1/Token</span></span><br><span class="line">(<span class="keyword">new</span> TokenGet())-&gt;goCheck();</span><br></pre></td></tr></table></figure>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// api/validate/TokenGet</span></span><br><span class="line"><span class="keyword">protected</span> $rule = [</span><br><span class="line">    <span class="comment">// 在验证器基类中定义isNotEmpty()方法</span></span><br><span class="line">    <span class="string">'code'</span> =&gt; <span class="string">'require|isNotEmpty'</span></span><br><span class="line">];</span><br><span class="line"></span><br><span class="line"><span class="keyword">protected</span> $message = [</span><br><span class="line">    <span class="string">'code'</span> =&gt; <span class="string">'code必填！'</span></span><br><span class="line">];</span><br></pre></td></tr></table></figure>
<h3 id="9-4567-实现-token-身份权限体系"><a class="markdownIt-Anchor" href="#9-4567-实现-token-身份权限体系"></a> 9-4/5/6/7 实现 Token 身份权限体系</h3>
<p>1.获取微信生成的 code 码，并将其作为参数，传递给微信接口来获得 openid 和 access_token 等相关信息[openid/session_key]</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// api/controller/v1/Token</span></span><br><span class="line">$userToken = <span class="keyword">new</span> UserToken($code);</span><br><span class="line">$token = $userToken-&gt;get();</span><br></pre></td></tr></table></figure>
<p><strong>2.封装 Service 层，实现 Token 令牌的获取</strong>[重点]</p>
<p>1） 配置微信小程序相关参数[app_id app_secret login_url]</p>
<p>2.1.1 在配置文件中设置微信小程序的相关参数</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// config/extra/wx.php</span></span><br><span class="line"><span class="keyword">return</span> [</span><br><span class="line">    <span class="string">'app_id'</span> =&gt; <span class="string">'XXXXXXXXX'</span>,</span><br><span class="line">    <span class="string">'app_secret'</span> =&gt; <span class="string">'XXXXXXXXX'</span>,</span><br><span class="line">    <span class="string">'login_url'</span> =&gt; <span class="string">"https://api.weixin.qq.com/sns/jscode2session?"</span> . <span class="string">"appid=%s&amp;secret=%s&amp;js_code=%s&amp;grant_type=authorization_code"</span></span><br><span class="line">];</span><br></pre></td></tr></table></figure>
<p>2.1.2 创建 Service 层的 UserToken 处理类，定义参数为私有属性</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// api/service/UserToken.php</span></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">app</span>\<span class="title">api</span>\<span class="title">service</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">use</span> <span class="title">app</span>\<span class="title">lib</span>\<span class="title">exception</span>\<span class="title">WechatException</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">app</span>\<span class="title">lib</span>\<span class="title">exception</span>\<span class="title">TokenException</span>;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">UserToken</span> <span class="keyword">extends</span> <span class="title">Token</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">    <span class="keyword">protected</span> $code;</span><br><span class="line">    <span class="keyword">protected</span> $appid;</span><br><span class="line">    <span class="keyword">protected</span> $appSecret;</span><br><span class="line">    <span class="keyword">protected</span> $loginUrl;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>2） 拼接参数，并使用 curl 模拟 http 请求微信服务器，并获取返回结果</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// api/service/UserToken.php</span></span><br><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span><span class="params">($code)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">$this</span>-&gt;code      = $code;</span><br><span class="line">    <span class="keyword">$this</span>-&gt;appid     = config(<span class="string">'wx.app_id'</span>);</span><br><span class="line">    <span class="keyword">$this</span>-&gt;appSecret = config(<span class="string">'wx.app_secret'</span>);</span><br><span class="line">    <span class="keyword">$this</span>-&gt;loginUrl  = sprintf(</span><br><span class="line">        config(<span class="string">'wx.login_url'</span>),</span><br><span class="line">        <span class="keyword">$this</span>-&gt;appid, <span class="keyword">$this</span>-&gt;appSecret, <span class="keyword">$this</span>-&gt;code</span><br><span class="line">    );</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">get</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    $result = curl_get(<span class="keyword">$this</span>-&gt;loginUrl);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>在公共方法文件中定义 curl 模拟 http 请求的方法：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// application/common.php</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">curl_get</span><span class="params">($url, &amp;$httpCode = <span class="number">0</span>)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="comment">//1、初始化curl</span></span><br><span class="line">    $curl = curl_init();</span><br><span class="line"></span><br><span class="line">    <span class="comment">//2、告诉curl,请求的地址</span></span><br><span class="line">    curl_setopt($curl, CURLOPT_URL, $url);</span><br><span class="line">    <span class="comment">//3、将请求的数据返回，而不是直接输出</span></span><br><span class="line">    curl_setopt($curl, CURLOPT_RETURNTRANSFER, <span class="keyword">true</span>);</span><br><span class="line"></span><br><span class="line">    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, <span class="number">0</span>);</span><br><span class="line">    curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, <span class="number">10</span>);</span><br><span class="line"></span><br><span class="line">    $fileContents = curl_exec($curl); <span class="comment">// 执行操作</span></span><br><span class="line">    curl_close($curl); <span class="comment">// 关键CURL会话</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> $fileContents; <span class="comment">// 返回数据</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>3） 请求微信接口失败[微信内部错误/程序编写出错]的异常处理</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// api/service/UserToken.php get()</span></span><br><span class="line">$wxResult = json_decode($result, <span class="keyword">true</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (<span class="keyword">empty</span>($wxResult)) &#123;</span><br><span class="line">    <span class="comment">// 经验总结得：如果返回的结果为空[没有返回错误信息和错误代码]，则是微信服务器接口的问题，直接抛出异常一颗</span></span><br><span class="line">    <span class="keyword">throw</span> <span class="keyword">new</span> \<span class="keyword">Exception</span>(<span class="string">'获取session_key及openID异常，微信内部错误'</span>);</span><br><span class="line">&#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    $loginFail = <span class="keyword">isset</span>($wxResult[<span class="string">'errcode'</span>]);</span><br><span class="line">    <span class="comment">// 程序传递的参数出错时，微信服务器会返回错误码和错误提示信息</span></span><br><span class="line">    <span class="keyword">if</span> ($loginFail) &#123;</span><br><span class="line">        <span class="keyword">$this</span>-&gt;processLoginErr($wxResult);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>调用微信 Token 请求接口调用出错时的处理：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// api/service/UserToken.php</span></span><br><span class="line"><span class="keyword">private</span> <span class="function"><span class="keyword">function</span> <span class="title">processLoginErr</span><span class="params">($wxResult)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">throw</span> <span class="keyword">new</span> WechatException(</span><br><span class="line">        [</span><br><span class="line">            <span class="string">'msg'</span>       =&gt; $wxResult[<span class="string">'errmsg'</span>],</span><br><span class="line">            <span class="string">'errorCode'</span> =&gt; $wxResult[<span class="string">'errcode'</span>],</span><br><span class="line">        ]</span><br><span class="line">    );</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>4） <strong>成功获取微信接口返回数据后的操作[存储 openid、生成令牌、写入缓存、返回令牌]</strong></p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// api/service/UserToken.php get()</span></span><br><span class="line"><span class="keyword">return</span> <span class="keyword">$this</span>-&gt;grantToken($wxResult);</span><br></pre></td></tr></table></figure>
<p>2.4.1 存储 openid</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// api/service/UserToken.php</span></span><br><span class="line"><span class="keyword">private</span> <span class="function"><span class="keyword">function</span> <span class="title">grantToken</span><span class="params">($wxResult)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    $now = time();</span><br><span class="line">    <span class="comment">// 1.拿到openid</span></span><br><span class="line">    $openid     = $wxResult[<span class="string">'openid'</span>];</span><br><span class="line">    <span class="comment">// $sessionKey = $wxResult['session_key'];</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 2.查看数据库中该openid的记录是否已经存在[同一个用户的openid始终保持不变]</span></span><br><span class="line">    $user = model(<span class="string">'user'</span>)-&gt;getByOpenId($openid);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 3.如果存在，则不处理； 如果不存在，那么新增一条user记录</span></span><br><span class="line">    <span class="keyword">if</span> ($user) &#123;</span><br><span class="line">        $uid = $user-&gt;id;</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        $uid = <span class="keyword">$this</span>-&gt;newUser($openid);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>根据 openid 查询是否已经存在该用户</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// api/model/User.php</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="function"><span class="keyword">function</span> <span class="title">getByOpenId</span><span class="params">($openid)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    $user = <span class="keyword">self</span>::where(<span class="string">'openid'</span>, <span class="string">'='</span>, $openid)-&gt;find();</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> $user;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>创建用户</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// api/service/UserToken.php</span></span><br><span class="line"><span class="keyword">private</span> <span class="function"><span class="keyword">function</span> <span class="title">newUser</span><span class="params">($openid)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    $user = model(<span class="string">'user'</span>)-&gt;create([</span><br><span class="line">       <span class="string">'openid'</span> =&gt; $openid</span><br><span class="line">    ]);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> $user-&gt;id;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>2.4.2 准备缓存数据(缓存的值)[微信返回数据(openid|session_key) + uid(用户服务器中保存的用户记录 id) + scope(用户权限，值越大，权限越高) ]</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// api/service/UserToken.php  grantToken()</span></span><br><span class="line"><span class="comment">// 4.生成令牌，准备缓存数据，写入缓存 [获取用户的相关信息]</span></span><br><span class="line"><span class="comment">// 4.1 准备缓存数据</span></span><br><span class="line">$cachedValue = <span class="keyword">$this</span>-&gt;prepareCachedValue($wxResult, $uid);</span><br></pre></td></tr></table></figure>
<p>准备缓存数据值的方法[缓存的值]</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// api/service/UserToken.php</span></span><br><span class="line"><span class="keyword">private</span> <span class="function"><span class="keyword">function</span> <span class="title">prepareCachedValue</span><span class="params">($wxResult, $uid)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    $cachedValue = $wxResult;</span><br><span class="line">    $cachedValue[<span class="string">'uid'</span>] = $uid;</span><br><span class="line">    $cachedValue[<span class="string">'scope'</span>] = <span class="number">16</span>; <span class="comment">// 数值越大，权限越多</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> $cachedValue;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>2.4.3 写入缓存[令牌+微信返回数据+有效期]</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// api/service/UserToken.php  grantToken()</span></span><br><span class="line"><span class="comment">// 4.2 写入缓存，并返回令牌</span></span><br><span class="line">$token = <span class="keyword">$this</span>-&gt;saveToCache($cachedValue);</span><br></pre></td></tr></table></figure>
<p>2.4.3.1 生成令牌(缓存的键)[随机字符串+时间戳+盐]</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 令牌是用户程序生成的随机字符串，与微信服务器无关</span></span><br><span class="line"><span class="comment">// api/service/UserToken.php  saveToCache()</span></span><br><span class="line">$key = <span class="keyword">self</span>::generateToken();</span><br></pre></td></tr></table></figure>
<p>在服务器层构建 Token 基类，处理用户登录 Token 和后续的其他 Token 信息[service 下 UserToken 继承该基类]</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// api/service/Token.php</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="function"><span class="keyword">function</span> <span class="title">generateToken</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="comment">// 用三组字符串，进行md5加密 [加强安全性]</span></span><br><span class="line">    <span class="comment">// 1.32个字符组成一组随机字符串</span></span><br><span class="line">    $randChars = getRandChar(<span class="number">32</span>);</span><br><span class="line">    <span class="comment">// 2.时间戳</span></span><br><span class="line">    $timestamp = $_SERVER[<span class="string">'REQUEST_TIME_FLOAT'</span>];</span><br><span class="line">    <span class="comment">// 3.盐</span></span><br><span class="line">    $salt = config(<span class="string">'secure.token_salt'</span>);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> md5($randChars.$timestamp.$salt);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>公共方法中定义生成指定长度的随机字符串</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// application/common.php</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">getRandChar</span><span class="params">($length)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    $str    = <span class="keyword">null</span>;</span><br><span class="line">    $strPol = <span class="string">"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"</span>;</span><br><span class="line">    $max    = strlen($strPol) - <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> ($i = <span class="number">0</span>; $i &lt; $length; $i++) &#123;</span><br><span class="line">        $str .= $strPol[rand(<span class="number">0</span>, $max)];</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> $str;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>创建安全配置文件[盐：随机字符串]</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// extra/secure.php</span></span><br><span class="line"><span class="keyword">return</span> [</span><br><span class="line">    <span class="string">'token_salt'</span> =&gt; <span class="string">'E7epHZhrTfgQ'</span></span><br><span class="line">];</span><br></pre></td></tr></table></figure>
<p>2.4.3.2 配置文件中设置 cache 缓存的有效期</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">创建安全配置文件[盐：随机字符串]</span><br><span class="line"></span><br><span class="line">```php</span><br><span class="line"><span class="comment">// extra/setting.php</span></span><br><span class="line"><span class="string">'token_expire_in'</span> =&gt; <span class="number">7200</span></span><br></pre></td></tr></table></figure>
<p>2.4.3.3 创建缓存文件</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> <span class="function"><span class="keyword">function</span> <span class="title">saveToCache</span><span class="params">($cachedValue)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    $key = <span class="keyword">self</span>::generateToken();</span><br><span class="line">    $value = json_encode($cachedValue);</span><br><span class="line">    <span class="comment">// 设置缓存失效时间</span></span><br><span class="line">    $expire_in = config(<span class="string">'setting.token_expire_in'</span>);</span><br><span class="line"></span><br><span class="line">    $request = cache($key, $value, $expire_in);</span><br><span class="line">    <span class="keyword">if</span> (!$request) &#123;</span><br><span class="line">        <span class="comment">// 令牌缓存出错</span></span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> TokenException([</span><br><span class="line">            <span class="string">'msg'</span> =&gt; <span class="string">'服务器缓存异常'</span>,</span><br><span class="line">            <span class="string">'errorCode'</span> =&gt; <span class="number">10005</span></span><br><span class="line">        ]);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> $key;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>2.4.4 返回令牌</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// api/service/UserToken.php  grantToken()</span></span><br><span class="line"><span class="comment">// 4.3 写入缓存，并返回令牌</span></span><br><span class="line"><span class="keyword">return</span> $token;</span><br></pre></td></tr></table></figure>
<p>3.异常处理类</p>
<p>3.1 微信内部错误[直接抛出异常]</p>
<p>3.2 微信接口调用出错[微信相关异常处理类 WechatException]</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">WechatException</span> <span class="keyword">extends</span> <span class="title">BaseException</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">    <span class="keyword">public</span> $code = <span class="number">404</span>;</span><br><span class="line">    <span class="keyword">public</span> $msg = <span class="string">'微信服务器接口调用失败'</span>;</span><br><span class="line">    <span class="keyword">public</span> $errorCode = <span class="number">999</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>3.3 缓存 Token 出错[Token 异常处理类 TokenException]</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">TokenException</span> <span class="keyword">extends</span> <span class="title">BaseException</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">    <span class="keyword">public</span> $code = <span class="number">401</span>;</span><br><span class="line">    <span class="keyword">public</span> $msg = <span class="string">'Token已过期或无效Token'</span>;</span><br><span class="line">    <span class="keyword">public</span> $errorCode = <span class="number">10001</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="9-8-获取请求参数-code-并调用-php-接口借助微信开发工具"><a class="markdownIt-Anchor" href="#9-8-获取请求参数-code-并调用-php-接口借助微信开发工具"></a> 9-8 获取请求参数 code 并调用 PHP 接口[借助微信开发工具]</h3>
<h4 id="1微信开发者工具中配置"><a class="markdownIt-Anchor" href="#1微信开发者工具中配置"></a> 1.微信开发者工具中配置：</h4>
<blockquote>
<p>设置好 app_key 后，需要将 “详情” 中的 “不校验合法域名、web-view(业务域名)、TLS 版本以及 HTTPS 证书” 勾选上（在本地测试，没有远程访问的服务器或远程服务器访问的域名没有 https 证书）</p>
</blockquote>
<h4 id="2小程序代码"><a class="markdownIt-Anchor" href="#2小程序代码"></a> 2.小程序代码：</h4>
<p>(1) 在 config 中定义 restUrl</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Protoss/utils/config.js [设置本地测试的域名基地址]</span></span><br><span class="line">Config.restUrl = <span class="string">"http://mypro.com/api/v1/"</span>;</span><br></pre></td></tr></table></figure>
<p>(2)在登录方法中获取 code</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 在小程序登录调用wx.login()方法中输出code，然后使用接口请求工具将code作为post请求的参数，进行调用</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// Protoss/utils/token.js getTokenFromServer()</span></span><br><span class="line">wx.login(&#123;</span><br><span class="line">  success: <span class="function"><span class="keyword">function</span>(<span class="params">res</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">"code: "</span> + res.code);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>
<h4 id="3请求-php-接口获取-token"><a class="markdownIt-Anchor" href="#3请求-php-接口获取-token"></a> 3.请求 PHP 接口获取 Token</h4>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 引用使用es6的module引入和定义</span></span><br><span class="line"><span class="comment">// 全局变量以g_开头</span></span><br><span class="line"><span class="comment">// 私有函数以_开头</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> &#123; Config &#125; <span class="keyword">from</span> <span class="string">"config.js"</span>;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Token</span> </span>&#123;</span><br><span class="line">  <span class="keyword">constructor</span>() &#123;</span><br><span class="line">    <span class="keyword">this</span>.tokenUrl = Config.restUrl + <span class="string">"token/user"</span>;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  verify() &#123;</span><br><span class="line">    <span class="keyword">var</span> token = wx.getStorageSync(<span class="string">"token"</span>);</span><br><span class="line">    <span class="keyword">if</span> (!token) &#123;</span><br><span class="line">      <span class="keyword">this</span>.getTokenFromServer();</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  getTokenFromServer(callBack) &#123;</span><br><span class="line">    <span class="keyword">var</span> that = <span class="keyword">this</span>;</span><br><span class="line">    wx.login(&#123;</span><br><span class="line">      success: <span class="function"><span class="keyword">function</span>(<span class="params">res</span>) </span>&#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">"code: "</span> + res.code);</span><br><span class="line">        wx.request(&#123;</span><br><span class="line">          url: that.tokenUrl,</span><br><span class="line">          method: <span class="string">"POST"</span>,</span><br><span class="line">          data: &#123;</span><br><span class="line">            code: res.code</span><br><span class="line">          &#125;,</span><br><span class="line">          success: <span class="function"><span class="keyword">function</span>(<span class="params">res</span>) </span>&#123;</span><br><span class="line">            <span class="built_in">console</span>.log(<span class="string">"token： "</span> + res.data.token);</span><br><span class="line">            wx.setStorageSync(<span class="string">"token"</span>, res.data.token);</span><br><span class="line">            callBack &amp;&amp; callBack(res.data.token);</span><br><span class="line">          &#125;</span><br><span class="line">        &#125;);</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> &#123; Token &#125;;</span><br></pre></td></tr></table></figure>
<p><strong>【补充说明】</strong>：</p>
<p>(1) 需要调试时，将 XDEBUG 参数拼接到<code>this.tokenUrl</code>即可</p>
<p>(2) 如果没有输出 code, 需要关闭开发者工具后再重新启动，会自动调用该方法，并输出 code<br>
[调用过生成的 token 已经被存储到浏览器的 Storage 中，便不会再调用 Token 请求接口，从而不产生 code]</p>
<h3 id="9-9-商品详情接口"><a class="markdownIt-Anchor" href="#9-9-商品详情接口"></a> 9-9 商品详情接口</h3>
<p>(1) 定义控制器方法 <code>getOne($id)</code></p>
<p>(2) 定义路由 <code>api/:version/product/:id</code></p>
<p>(3) 模型类实现[隐藏部分字段、设置数据表关联、实现数据库查询]</p>
<blockquote>
<p>Product =&gt; properties =&gt; ProductProperty =&gt; 商品属性值[品名、口味、产地、保质期]<br>
Product =&gt; imgs =&gt; Image =&gt; 商品主图<br>
ProductImage =&gt; imgs.imgUrl =&gt; Image =&gt; 商品详情图</p>
</blockquote>
<p>(4) 异常处理信息提示</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">[</span><br><span class="line">    <span class="string">'msg'</span>       =&gt; <span class="string">'当前产品无详情'</span>,</span><br><span class="line">    <span class="string">'errorCode'</span> =&gt; <span class="number">20001</span></span><br><span class="line">]</span><br></pre></td></tr></table></figure>
<h3 id="9-10-1-路由变量规则"><a class="markdownIt-Anchor" href="#9-10-1-路由变量规则"></a> 9-10-1 路由变量规则</h3>
<p>1.路由匹配规则在项目中的应用。</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Route::get(<span class="string">'api/:version/product/recent'</span>, <span class="string">'api/:version.Product/getRecent'</span>);</span><br><span class="line">Route::get(<span class="string">'api/:version/product/:id'</span>, <span class="string">'api/:version.Product/getOne'</span>);</span><br></pre></td></tr></table></figure>
<p>2.存在的问题</p>
<p>目前调用接口都不存在问题，但是当将<code>:id</code>行放到<code>recent</code>行之前后，在调用<code>recent</code>路由时，则会因为优先匹配<code>:id</code>对应的路由，<br>
此时则会因为参数校验不通过而报错。</p>
<p>3.解决之道：</p>
<p>对路由匹配规则进行限定，设置变量规则，对于<code>:id</code>行，限定只有当参数为数值时才匹配到当前行。即设置 <code>$id</code>的变量规则</p>
<p>变量规则：为变量用正则的方式指定变量规则，弥补了动态变量无法限制具体的类型问题，并且支持全局规则设置。</p>
<p>4.代码实现[设置变量规则]</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Route::get(<span class="string">'api/:version/product/:id'</span>, <span class="string">'api/:version.Product/getOne'</span>, [], [<span class="string">'id'</span>=&gt;<span class="string">'\d+'</span>]);</span><br></pre></td></tr></table></figure>
<h3 id="9-10-2-路由分组"><a class="markdownIt-Anchor" href="#9-10-2-路由分组"></a> 9-10-2 路由分组</h3>
<p>对路由配置文件中，具有相同路由前缀的路由归为同一路由组，例如：</p>
<p>对于几个对应产品信息的路由，</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Route::get(<span class="string">'api/:version/product/recent'</span>, <span class="string">'api/:version.Product/getRecent'</span>);</span><br><span class="line">Route::get(<span class="string">'api/:version/product/by_category'</span>, <span class="string">'api/:version.Product/getAllInCategory'</span>);</span><br><span class="line">Route::get(<span class="string">'api/:version/product/:id'</span>, <span class="string">'api/:version.Product/getOne'</span>);</span><br></pre></td></tr></table></figure>
<p>可以分组到产品组路由下，</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 闭包方式注册路由分组</span></span><br><span class="line">Route::group(<span class="string">'api/:version/product'</span>, <span class="function"><span class="keyword">function</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    Route::get(<span class="string">'recent'</span>, <span class="string">'api/:version.Product/getRecent'</span>);</span><br><span class="line">    Route::get(<span class="string">'by_category'</span>, <span class="string">'api/:version.Product/getAllInCategory'</span>);</span><br><span class="line">    Route::get(<span class="string">':id'</span>, <span class="string">'api/:version.Product/getOne'</span>, [], [<span class="string">'id'</span> =&gt; <span class="string">'\d+'</span>]);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>
<p>或者：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 数组方式注册路由分组</span></span><br><span class="line">Route::group(<span class="string">'api/:version/product'</span>, [</span><br><span class="line">    <span class="string">'recent'</span> =&gt; [<span class="string">'api/:version.Product/getRecent'</span>],</span><br><span class="line">    <span class="string">'by_category'</span> =&gt; [<span class="string">'api/:version.Product/getAllInCategory'</span>],</span><br><span class="line">    <span class="string">':id'</span> =&gt; [<span class="string">'api/:version.Product/getOne'</span>, [], [<span class="string">'id'</span> =&gt; <span class="string">'\d+'</span>]]</span><br><span class="line">],[<span class="string">'method'</span> =&gt; <span class="string">'get'</span>]);</span><br></pre></td></tr></table></figure>
<p>路由分组的方式定义路由，执行的效率会比一般形式高一点。</p>
<p>【注】路由分组的公共路由定义时，不能在末尾加<code>/</code>，否则会报控制器不存在的错误</p>
<h3 id="9-11-闭包函数构建查询器"><a class="markdownIt-Anchor" href="#9-11-闭包函数构建查询器"></a> 9-11 闭包函数构建查询器</h3>
<p>1.完成的商品详情的数据信息格式为：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">&quot;id&quot;: 11,</span><br><span class="line">&quot;name&quot;: &quot;贵妃笑 100克&quot;,</span><br><span class="line">&quot;price&quot;: &quot;0.01&quot;,</span><br><span class="line">&quot;stock&quot;: 994,</span><br><span class="line">&quot;main_img_url&quot;: &quot;http://mypro.com/static/images/product-dryfruit-a@6.png&quot;,</span><br><span class="line">&quot;summary&quot;: null,</span><br><span class="line">&quot;img_id&quot;: 39,</span><br><span class="line">&quot;imgs&quot;:[</span><br><span class="line">    &#123;</span><br><span class="line">        &quot;id&quot;: 4,</span><br><span class="line">        &quot;order&quot;: 1,</span><br><span class="line">        &quot;img_url&quot;:&#123;</span><br><span class="line">            &quot;url&quot;: &quot;http://mypro.com/static/images/detail-1@1-dryfruit.png&quot;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">        &quot;id&quot;: 5,</span><br><span class="line">        &quot;order&quot;: 2,</span><br><span class="line">        &quot;img_url&quot;:&#123;</span><br><span class="line">            &quot;url&quot;: &quot;http://mypro.com/static/images/detail-2@1-dryfruit.png&quot;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;,</span><br><span class="line">],</span><br><span class="line">&quot;properties&quot;:[</span><br><span class="line">    &#123;</span><br><span class="line">        &quot;id&quot;: 1,</span><br><span class="line">        &quot;name&quot;: &quot;品名&quot;,</span><br><span class="line">        &quot;detail&quot;: &quot;杨梅&quot;</span><br><span class="line">    &#125;,</span><br><span class="line">]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>2.问题：其中<code>imgs</code>的值为每个商品下的所有图片介绍，所以所有图片之间一定存在一定的顺序，其中<code>imgs</code>数组下的数据中存在<code>order</code>排序字段，如何对<code>imgs</code>的数据通过<code>order</code>进行排序？</p>
<p>3.【答】：使用闭包函数构建查询器【相当于拼接 sql】。</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">$product = <span class="keyword">self</span>::with([</span><br><span class="line">        <span class="string">'imgs'</span> =&gt; <span class="function"><span class="keyword">function</span><span class="params">($query)</span> </span>&#123;</span><br><span class="line">            $query-&gt;with([<span class="string">'imgUrl'</span>])-&gt;order(<span class="string">'order asc'</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    ])</span><br><span class="line">    -&gt;with([<span class="string">'properties'</span>])</span><br><span class="line">    -&gt;find($id);</span><br></pre></td></tr></table></figure>
<p>4.思路分析：</p>
<p>（1）要对 imgs 下的数据进行处理，需要获取到每组数据，然后对<code>order</code>字段进行排序。【通过闭包函数获取到每组数据】</p>
<p>（2）除了要对每组数据进行按<code>order</code>排序，还需要处理<code>img_url</code>。【通过 with 链式操作处理<code>img_url</code>】</p>
<p>5.关于闭包函数的理解：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">'imgs'</span> =&gt; <span class="function"><span class="keyword">function</span><span class="params">($query)</span> </span>&#123;</span><br><span class="line">    $query-&gt;with([<span class="string">'imgUrl'</span>])-&gt;order(<span class="string">'order asc'</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>对于数组<code>imgs</code>，通过闭包函数，获取到每组数据，其中<code>$query</code>即作为参数接收每组数据的值，然后再对每组数据的<code>img_url</code>通过 with 进行数据关联。</p>
<h3 id="9-12-用户收货地址"><a class="markdownIt-Anchor" href="#9-12-用户收货地址"></a> 9-12 用户收货地址</h3>
<p>1.需求说明：</p>
<p>用户收货地址接口信息需要进行身份验证，登录用户只能查看和操作自己的地址信息，未登录用户不能访问。</p>
<p>为简化操作，当前将用户和用户地址的关联关系设定为一对一。</p>
<p>2.思考点：</p>
<p>（1）对登录状态的判断：</p>
<p>当用户访问小程序时，调用<code>wx.login()</code>方法，并生成<code>code</code>,后台接口拿到 code 后生成 token，并用 token 以及配置的<code>app_id</code>和<code>app_secret</code>请求微信接口，并获取微信返回的<code>openid</code>等信息，存储到缓存中<br>
[以 token 为键，uid|wxResult|scope 组成的 json 数据为值]</p>
<p>所以，创建或修改用户地址信息时，在处理地址信息和用户信息的关联时，使用的用户信息，应当是当前登录用户的信息，而不能是客户端传递的用户信息参数[可能传递有误，导致误操作到其他用户的地址信息]</p>
<p>实现一定程度上的接口保护。</p>
<p>（2）传入参数的检验</p>
<p>验证器校验往往只能验证某个字段或某些字段的合法性，而客户端可能传入的参数比需要的参数多，或者传入了<code>uid</code>或者<code>user_id</code>，导致更新时覆盖了其他用户的数据信息，对系统的安全性造成影响，<br>
所以，在接收客户端传入参数时，需要进行多余字段的过滤。</p>
<p>（3）对手机号的验证</p>
<p>正则表达式的应用场景，正则模式<code>^1(3|4|5|6|7|8)[0-9]\d{8}$^</code></p>
<p>（4）<strong>通过模型关联，实现用户地址的新增和更新</strong>【新】</p>
<p>通过关联模型方法，创建数据</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 新增</span></span><br><span class="line">$user-&gt;address()-&gt;save($dataArray);</span><br></pre></td></tr></table></figure>
<p>通过关联模型属性，对当前属性对应的记录进行更新</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 更新</span></span><br><span class="line">$user-&gt;address-&gt;save($dataArray);</span><br></pre></td></tr></table></figure>
<p>（5）模型关联方法的选择：</p>
<p>模型关联方法的区分：</p>
<pre><code>有主键关联无主键 =》 belongsTo
无主键关联有主键 =》 hasOne|hasMany
</code></pre>
<p>（6）HTTP 状态码</p>
<p>200：操作成功，服务器已成功处理了请求。说明：<a href="https://blog.csdn.net/u014028956/article/details/47125403" target="_blank" rel="noopener">如果是对您的 robots.txt 文件显示此状态码，则表示 Googlebot 已成功检索到该文件</a></p>
<p>201：创建成功，表示服务器执行成功，并且创建了新的资源</p>
<p>设置接口调用成功后的状态码标识：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">return</span> json(<span class="keyword">new</span> SuccessMessage(), <span class="number">201</span>);</span><br></pre></td></tr></table></figure>
<h3 id="9-12-1-通过令牌获取用户标识"><a class="markdownIt-Anchor" href="#9-12-1-通过令牌获取用户标识"></a> 9-12-1 通过令牌获取用户标识</h3>
<ol>
<li>
<p>定义控制器方法 <code>createOrUpdate()</code></p>
</li>
<li>
<p>定义路由 <code>api/:version/address</code></p>
</li>
<li>
<p>验证器验证用户输入数据 [<code>name</code>, <code>mobile</code>, <code>province</code>, <code>city</code>, <code>country</code>, <code>detail</code>]</p>
</li>
<li>
<p>异常处理信息提示</p>
</li>
</ol>
<p>当数据不合法时抛出异常，而当操作成功时，也需要返回相应的数据信息。当前项目将抛出的成功信息也放在异常处理类库下。</p>
<h3 id="9-12-2-面向对象的方式封装获取-uid-方法"><a class="markdownIt-Anchor" href="#9-12-2-面向对象的方式封装获取-uid-方法"></a> 9-12-2 面向对象的方式封装获取 uid 方法</h3>
<p>1.通过令牌 token 即可获取缓存中对应的用户信息，而缓存中的信息包括<code>uid</code> <code>scope</code> <code>wxResult</code>[<code>openid</code> <code>session_key</code>]</p>
<p>而在 http 请求时，token 保存在 header 头信息中，获取头信息中<code>token</code>的方法：</p>
<p><code>$token = Request::instance()-&gt;header('token');</code></p>
<p>2.通过 json 键值对的键，获取 cache 数据</p>
<p><code>Cache::get($token)</code></p>
<p>3.增强项目的扩展性，可将通过 token 获取变量的方法进行封装。</p>
<p>4.代码实现：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="function"><span class="keyword">function</span> <span class="title">getCurrentTokenVar</span><span class="params">($key)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    $token = Request::instance()-&gt;header(<span class="string">'token'</span>);</span><br><span class="line">    $vars  = Cache::get($token);</span><br><span class="line">    <span class="keyword">if</span> ( ! $vars) &#123;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> TokenException();</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (!is_array($vars)) &#123;</span><br><span class="line">            $vars = json_decode($vars, <span class="keyword">true</span>);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (<span class="keyword">isset</span>($vars[$key])) &#123;</span><br><span class="line">            <span class="keyword">return</span> $vars[$key];</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="keyword">Exception</span>(<span class="string">'尝试获取的Token变量不存在'</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="function"><span class="keyword">function</span> <span class="title">getCurrentUid</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    $uid = <span class="keyword">self</span>::getCurrentTokenVar(<span class="string">'uid'</span>);</span><br><span class="line">    <span class="keyword">return</span> $uid;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="9-12-3-模型新增和更新"><a class="markdownIt-Anchor" href="#9-12-3-模型新增和更新"></a> 9-12-3 模型新增和更新</h3>
<p>通过用户模型，进行面向对象方式的新增和更新</p>
<p>（1）user 模型定义 address()关联方法，获取到用户地址信息，当用户地址信息不存在时，也通过<strong>关联模型方法</strong>，保存地址信息</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 新增</span></span><br><span class="line">$user-&gt;address()-&gt;save($dataArray);</span><br></pre></td></tr></table></figure>
<p>（2）user 模型通过 address()关联方法关联 user_address 数据表中对应的用户地址信息，通过关联获取的数据仍然可以作为模型的属性值使用，<br>
再通过<strong>关联模型属性</strong>，对当前属性对应的记录进行更新 [包含主键 id]</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 更新</span></span><br><span class="line">$user-&gt;address-&gt;save($dataArray);</span><br></pre></td></tr></table></figure>
<h3 id="9-12-4-参数过滤"><a class="markdownIt-Anchor" href="#9-12-4-参数过滤"></a> 9-12-4 参数过滤</h3>
<p>封装处理客户端传入的参数的方法，由于当前用户的信息是通过缓存获取的，为避免用户传入的参数造成错误修改，所以需要对客户端传入数据进行过滤，<br>
如果携带用户 id 参数，则抛出异常，不再继续处理。除此之外，对于传入的无效、多余数据，进行过滤，仅接收验证器需要验证的字段信息。</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">getDataByRule</span><span class="params">($params)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">isset</span>($params[<span class="string">'uid'</span>]) || <span class="keyword">isset</span>($params[<span class="string">'user_id'</span>])) &#123;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> ParameterException([</span><br><span class="line">            <span class="string">'msg'</span> =&gt; <span class="string">'参数中包含非法的参数名user_id或者uid'</span></span><br><span class="line">        ]);</span><br><span class="line">    &#125;</span><br><span class="line">    $newArray = [];</span><br><span class="line">    <span class="keyword">foreach</span> (<span class="keyword">$this</span>-&gt;rule <span class="keyword">as</span> $key =&gt; $value) &#123;</span><br><span class="line">        $newArray[$key] = $params[$key];</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> $newArray;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="9-12-5-接口测试"><a class="markdownIt-Anchor" href="#9-12-5-接口测试"></a> 9-12-5 接口测试</h3>
<p>1.需要的参数</p>
<ul>
<li>
<p>token: header 请求头 [通过微信小程序的开发者工具]</p>
</li>
<li>
<p>address 字段信息 [<code>name</code>, <code>mobile</code>, <code>province</code>, <code>city</code>, <code>country</code>, <code>detail</code>]</p>
<p>2.返回的数据</p>
</li>
</ul>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="attr">"code"</span>: <span class="number">201</span>,</span><br><span class="line">  <span class="attr">"msg"</span>: <span class="string">"ok"</span>,</span><br><span class="line">  <span class="attr">"errorCode"</span>: <span class="number">0</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>并且通过设置返回值为带状态码的 json 数据，<code>json(new SuccessMessage(), 201)</code>，可将 http 的状态码也设置为<code>201</code></p>

		</div>

		
			<div class="art-item-footer">
					
						<span class="art-item-left"><i class="icon icon-chevron-thin-left"></i> <a href="/2018/07/30/linux-ssh/" rel="prev" title="【SSH】使用SSH登录远程主机，并禁用密码登录">
							【SSH】使用SSH登录远程主机，并禁用密码登录
						</a>上一篇文章</span>
					
					
						<span class="art-item-right">下一篇文章：<a href="/2018/07/09/php-optimize/" rel="next"  title="PHP性能优化">
							PHP性能优化
						</a><i class="icon icon-chevron-thin-right"></i></span>
					
			</div>
		

		
			

    <div class="recommended_posts">
        <h3>推荐文章</h3>
        <ul>
            
                <li><a href="http://blog.i2arch.tech/2018/07/30/python-base/">【Python】安装与配置</a></li>
            
                <li><a href="http://blog.i2arch.tech/2018/07/30/linux-ssh/">【SSH】使用SSH登录远程主机，并禁用密码登录</a></li>
            
                <li><a href="http://blog.i2arch.tech/2018/07/09/php-optimize/">PHP性能优化</a></li>
            
                <li><a href="http://blog.i2arch.tech/2018/07/07/web-goserver/">【Linux】网站上线</a></li>
            
        </ul>
    </div>


		
	</section>

	

</article>
<script>
	window.subData = {
		title: '微信小程序结合ThinkPHP5实战项目（三）-- 微信登录与令牌',
		tools: true
	}
</script>

      </div>

      <!-- 右侧边栏组件 -->
      <aside class='l_side'>
        
      </aside>

      <div class="gotop">
          
    <a href='javascript:void(0)'>
        <i class="icon icon-arrow_upward flat-box">
        </i>
    </a>

      </div>
      <script>setLoadingBarProgress(60);</script>
    </div>
  </div>
  <footer id="footer" class="clearfix">

	<div class="social-wrapper">
  	
      
        <a href="https://github.com/zqunor" class="social github"
          target="_blank" rel="external">
          <span class="icon icon-github"></span>
        </a>
      
        <a href="https://www.cnblogs.com/zqunor" class="social zhihu"
          target="_blank" rel="external">
          <span class="icon icon-zhihu"></span>
        </a>
      
        <a href="/atom.xml" class="social rss"
          target="_blank" rel="external">
          <span class="icon icon-rss"></span>
        </a>
      
    
  </div>
  <div>Theme <a href='https://github.com/stkevintan/hexo-theme-material-flow' class="codename">MaterialFlow</a>  Powered by<a href="https://blog.i2arch.tech/" target="_blank">程序小工</a>.</div>

</footer>

  <script>setLoadingBarProgress(80);</script>
  

    <script src="//apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
    <script src='//cdn.bootcss.com/node-waves/0.7.5/waves.min.js'></script>
    <script src="//cdn.bootcss.com/scrollReveal.js/3.3.2/scrollreveal.min.js"></script>
    <script src="/js/jquery.fitvids.js"></script>
      <script>
        var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
        var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
        var ALGOLIA_API_KEY = "";
        var ALGOLIA_APP_ID = "";
        var ALGOLIA_INDEX_NAME = "";
        var AZURE_SERVICE_NAME = "";
        var AZURE_INDEX_NAME = "";
        var AZURE_QUERY_KEY = "";
        var BAIDU_API_ID = "fca5b83cf69f752ddc96a61ef64a3659";
        var SEARCH_SERVICE = "hexo";
        var ROOT = "/" || "/";
        if (!ROOT.endsWith('/')) ROOT += '/';
      </script>
      <script src="/js/search.js"></script>
        <script src="/js/app.js"></script>
  <script>setLoadingBarProgress(100);</script>
</body>
</html>
